//SPDX-FileCopyrightText: Copyright 2022-2024 深圳市同心圆网络有限公司
//SPDX-License-Identifier: GPL-3.0-only

package org_dao

import (
	"context"

	"atomgit.com/openlinksaas/api-server/dao/db_ns"
	"atomgit.com/openlinksaas/proto-gen-go.git/org_asset_api"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/mongo"
	"go.mongodb.org/mongo-driver/mongo/options"
)

type AssetInfoDbItem struct {
	AssetId      string `bson:"_id"`
	OrgId        string `bson:"orgId"`
	AssetCateId  string `bson:"assetCateId"`
	AssetNo      string `bson:"assetNo"`
	AssetDesc    string `bson:"assetDesc"`
	OwnerType    uint32 `bson:"ownerType"`
	OwnerId      string `bson:"ownerId"`
	CreateTime   int64  `bson:"createTime"`
	CreateUserId string `bson:"createUserId"`
	UpdateTime   int64  `bson:"updateTime"`
	UpdateUserId string `bson:"updateUserId"`
}

func (item *AssetInfoDbItem) ToAssetInfo() *org_asset_api.AssetInfo {
	return &org_asset_api.AssetInfo{
		AssetId:      item.AssetId,
		AssetNo:      item.AssetNo,
		AssetDesc:    item.AssetDesc,
		OwnerType:    org_asset_api.ASSET_OWNER_TYPE(item.OwnerType),
		OwnerId:      item.OwnerId,
		AssetCateId:  item.AssetCateId,
		CreateTime:   item.CreateTime,
		CreateUserId: item.CreateUserId,
		UpdateTime:   item.UpdateTime,
		UpdateUserId: item.UpdateUserId,
	}
}

type _AssetDao struct {
	mc *mongo.Collection
}

func newAssetDao(db *mongo.Database) (*_AssetDao, error) {
	mc := db.Collection(db_ns.DB_NS_ORG + "asset")
	_, err := mc.Indexes().CreateMany(context.Background(), []mongo.IndexModel{
		{
			Keys: bson.D{{"orgId", 1}, {"assetCateId", 1}},
		},
		{
			Keys: bson.D{{"orgId", 1}, {"ownerId", 1}},
		},
	})
	if err != nil {
		return nil, err
	}
	return &_AssetDao{mc: mc}, nil
}

func (db *_AssetDao) Insert(ctx context.Context, dbItem *AssetInfoDbItem) error {
	_, err := db.mc.InsertOne(ctx, dbItem)
	return err
}

func (db *_AssetDao) Get(ctx context.Context, orgId, assetId string) (*AssetInfoDbItem, error) {
	retItem := &AssetInfoDbItem{}
	err := db.mc.FindOne(ctx, bson.M{"_id": assetId, "orgId": orgId}).Decode(retItem)
	return retItem, err
}

func (db *_AssetDao) Exist(ctx context.Context, orgId, assetId string) (bool, error) {
	count, err := db.mc.CountDocuments(ctx, bson.M{"_id": assetId, "orgId": orgId})
	return count > 0, err
}

func (db *_AssetDao) Remove(ctx context.Context, orgId, assetId string) error {
	_, err := db.mc.DeleteOne(ctx, bson.M{"_id": assetId, "orgId": orgId})
	return err
}

func (db *_AssetDao) RemoveByOrg(ctx context.Context, orgId string) error {
	_, err := db.mc.DeleteMany(ctx, bson.M{"orgId": orgId})
	return err
}

func (db *_AssetDao) ListByDepartMent(ctx context.Context, orgId, departMentId string) ([]*AssetInfoDbItem, error) {
	cursor, err := db.mc.Find(ctx, bson.M{
		"orgId":     orgId,
		"ownerType": uint32(org_asset_api.ASSET_OWNER_TYPE_ASSET_OWNER_DEPART_MENT),
		"ownerId":   departMentId,
	}, options.Find().SetSort(bson.M{"createTime": -1}))
	if err != nil {
		return nil, err
	}
	retList := []*AssetInfoDbItem{}
	err = cursor.All(ctx, &retList)
	return retList, err
}

func (db *_AssetDao) ListByMember(ctx context.Context, orgId string, memberUserIdList []string) ([]*AssetInfoDbItem, error) {
	if len(memberUserIdList) == 0 {
		return []*AssetInfoDbItem{}, nil
	}
	cursor, err := db.mc.Find(ctx, bson.M{
		"orgId":     orgId,
		"ownerType": uint32(org_asset_api.ASSET_OWNER_TYPE_ASSET_OWNER_MEMBER),
		"ownerId":   bson.M{"$in": memberUserIdList},
	}, options.Find().SetSort(bson.M{"createTime": -1}))
	if err != nil {
		return nil, err
	}
	retList := []*AssetInfoDbItem{}
	err = cursor.All(ctx, &retList)
	return retList, err
}

func (db *_AssetDao) CountByCate(ctx context.Context, orgId, assetCateId string) (uint32, error) {
	count, err := db.mc.CountDocuments(ctx, bson.M{"orgId": orgId, "assetCateId": assetCateId})
	return uint32(count), err
}

func (db *_AssetDao) CountByDepartMent(ctx context.Context, orgId, departMentId string) (uint32, error) {
	count, err := db.mc.CountDocuments(ctx, bson.M{
		"orgId":     orgId,
		"ownerType": uint32(org_asset_api.ASSET_OWNER_TYPE_ASSET_OWNER_DEPART_MENT),
		"ownerId":   departMentId})
	return uint32(count), err
}

func (db *_AssetDao) UpdateBaseInfo(ctx context.Context, orgId, assetId, assetNo, assetDesc, updateUserId string, updateTime int64) error {
	_, err := db.mc.UpdateOne(ctx, bson.M{"_id": assetId, "orgId": orgId},
		bson.M{"$set": bson.M{
			"assetNo":      assetNo,
			"assetDesc":    assetDesc,
			"updateUserId": updateUserId,
			"updateTime":   updateTime,
		}})
	return err
}

func (db *_AssetDao) UpdateCate(ctx context.Context, orgId, assetId, assetCateId, updateUserId string, updateTime int64) error {
	_, err := db.mc.UpdateOne(ctx, bson.M{"_id": assetId, "orgId": orgId},
		bson.M{"$set": bson.M{
			"assetCateId":  assetCateId,
			"updateUserId": updateUserId,
			"updateTime":   updateTime,
		}})
	return err
}

func (db *_AssetDao) UpdateOwner(ctx context.Context, orgId, assetId string, ownerType uint32, ownerId, updateUserId string, updateTime int64) error {
	_, err := db.mc.UpdateOne(ctx, bson.M{"_id": assetId, "orgId": orgId},
		bson.M{"$set": bson.M{
			"ownerType":    ownerType,
			"ownerId":      ownerId,
			"updateUserId": updateUserId,
			"updateTime":   updateTime,
		}})
	return err
}
